﻿using Microsoft.VisualStudio.TestTools.UnitTesting;
using Stack.Entities;
using Core.AbstractEntities;

namespace TestHP48CSharp48
{
    /// <summary>
    /// Test for the hpile
    /// </summary>
    [TestClass]
    public class UnitTest_hpileOperation
    {
        /// <summary>
        /// Case 1.01 : Instance hpile is not null
        /// </summary>
        [TestMethod]
        public void TestHpile_IsNotNull()
        {
            HpPile hpile = new HpPile();
            Assert.IsNotNull(hpile, "The instance doesn't exist!");
        }
        /// <summary>
        /// Case 1.02 : hpile add differents type of elements in the same hpile
        /// </summary>
        [TestMethod]
        public void TestHpile_AddElements()
        {
            HpPile hpile = new HpPile();
            InitialiseForTesthpile(hpile);

            Assert.AreEqual(1, hpile.Get(0).Value);
            Assert.AreEqual("this is a string", hpile.Get(1).Value);
            Assert.AreEqual('c', hpile.Get(2).Value);
            Assert.AreEqual(3.141516, hpile.Get(3).Value);
        }
        /// <summary>
        /// Case 1.03 : hpile pop the last element
        /// </summary>
        [TestMethod]
        public void TestHpile_Pop()
        {
            HpPile hpile = new HpPile();
            InitialiseForTesthpile(hpile);
            hpile.Pop();
            Assert.AreEqual(3, hpile.Count, "Pop doesn't work");
            Assert.AreEqual(1, hpile.Get(0).Value);
            Assert.AreEqual("this is a string", hpile.Get(1).Value);
            Assert.AreEqual('c', hpile.Get(2).Value);
        }
        /// <summary>
        /// Case 1.04 : hpile is a single collection of differents types of elements
        /// </summary>
        [TestMethod]
        public void TestHpile_IsCollection()
        {
            HpPile hpile = new HpPile();
            InitialiseForTesthpile(hpile);
            int count = 0;
            foreach (var item in hpile)
            {
                switch (count)
                {
                    case 0:
                        Assert.AreEqual(1, hpile.Get(0).Value);
                        break;
                    case 1:
                        Assert.AreEqual("this is a string", hpile.Get(1).Value);
                        break;
                    case 2:
                        Assert.AreEqual('c', hpile.Get(2).Value);
                        break;
                    case 3:
                        Assert.AreEqual(3.141516, hpile.Get(3).Value);
                        break;
                    default:
                        break;
                }
                count++;
            }
        }
        /// <summary>
        /// Case 1.05 :  
        /// The two last elements int the hpile can switch of position
        /// This operation is called "SWAP"
        /// </summary>
        [TestMethod]
        public void TestHpile_SwapElementInhpile()
        {
            HpPile hpile = new HpPile();
            InitialiseForTesthpile(hpile);
            hpile.Swap();
            Assert.AreEqual(1, hpile.Get(0).Value);
            Assert.AreEqual("this is a string", hpile.Get(1).Value);
            Assert.AreEqual(3.141516, hpile.Get(2).Value);
            Assert.AreEqual('c', hpile.Get(3).Value);
        }
        /// <summary>
        /// Case 1.06 :  
        /// The user can enter operators (+, -, / *, etc)
        /// The system execute the operation with the last two elements entered
        /// and the result of the operation will be inserted in the hpile
        /// </summary>
        [TestMethod]
        public void TestHpile_Operators()
        {
            HpPile hpile = new HpPile();
            InitialiseForTesthpile(hpile);
            hpile.AddElement(new HpElement() { Value = 5 });
            hpile.AddElement(new HpElement() { Value = 6 });
            //Add the '+' operator
            hpile.AddElement(new HpElement() { Value = '+' });
            Assert.AreEqual(11, hpile.Get(4).Value, "Operator '+' doesn't work properly");
            hpile.AddElement(new HpElement() { Value = 60 });
            hpile.AddElement(new HpElement() { Value = 20 });
            //Add the '-' operator
            hpile.AddElement(new HpElement() { Value = '-' });
            Assert.AreEqual(-40, hpile.Get(5).Value, "Operator '-' doesn't work properly");
            hpile.AddElement(new HpElement() { Value = 3 });
            hpile.AddElement(new HpElement() { Value = 4 });
            //Add the '*' operator
            hpile.AddElement(new HpElement() { Value = '*' });
            Assert.AreEqual(12, hpile.Get(6).Value, "Operator '*' doesn't work properly");
            hpile.AddElement(new HpElement() { Value = 2 });
            hpile.AddElement(new HpElement() { Value = 50 });
            //Add the '*' operator
            hpile.AddElement(new HpElement() { Value = '/' });
            Assert.AreEqual(25, hpile.Get(7).Value, "Operator '/' doesn't work properly");
        }
        /// <summary>
        /// Case 1.09 :  
        /// User Case 1.09 : The System Process list and arrays {} []
        /// </summary>
        [TestMethod]
        public void TestHpile_ListArrays()
        {
            HpPile hpile = new HpPile();
            InitialiseForTesthpile(hpile);
            hpile.AddElement(new HpElement() { Value = "{1 2 3 4}" });
            Assert.AreEqual("{1 2 3 4}", hpile.Get(4).Value);
        }
        /// <summary>
        /// Case 1.10 :  
        /// User Case 1.10 : Operations can be applied to lists and arrays {} [] 
        /// </summary>
        [TestMethod]
        public void TestHpile_ListArraysOperations()
        {
            HpPile hpile = new HpPile();
            InitialiseForTesthpile(hpile);
            hpile.AddElement(new HpElement() { Value = "{1 2 3 4}" });
            hpile.AddElement(new HpElement() { Value = 4 });
            hpile.AddElement(new HpElement() { Value = '+' });
            Assert.AreEqual("{5 6 7 8}", hpile.Get(4).Value);
            hpile.AddElement(new HpElement() { Value = 5 });
            hpile.AddElement(new HpElement() { Value = '*' });
            Assert.AreEqual("{25 30 35 40}", hpile.Get(4).Value);
            hpile.AddElement(new HpElement() { Value = 2 });
            hpile.AddElement(new HpElement() { Value = '/' });
            Assert.AreEqual("{12,5 15 17,5 20}", hpile.Get(4).Value);
            hpile.AddElement(new HpElement() { Value = 0.5 });
            hpile.AddElement(new HpElement() { Value = '-' });
            Assert.AreEqual("{12 14,5 17 19,5}", hpile.Get(4).Value);
        }
        /// <summary>
        /// Case 1.07 :  
        /// Reverse all the elements int the hpile can switch of position
        /// This operation is called "REVERSE"
        /// </summary>
        //[TestMethod]
        //public void Testhpile_ReverseElementsInhpile()
        //{
        //    hpile hpile = new hpile();
        //    InitialiseForTesthpile(hpile);

        //    hpile.Reverse();

        //    Assert.AreEqual(1, hpile.Get(3));
        //    Assert.AreEqual("this is a string", hpile.Get(2));
        //    Assert.AreEqual('c', hpile.Get(1));
        //    Assert.AreEqual(3.141516, hpile.Get(0));
        //}

        /// <summary>
        ///Initialitation of the elements in the pile
        /// </summary>
        /// <param name="hpile">Collection</param>
        private static void InitialiseForTesthpile(HpPile hpile)
        {
            HpElement element1 = new HpElement();
            element1.Value = 1;

            HpElement element2 = new HpElement();
            element2.Value = "this is a string";

            HpElement element3 = new HpElement();
            element3.Value = 'c';

            HpElement element4 = new HpElement();
            element4.Value = 3.141516;

            //Add element integer
            hpile.AddElement(element1);
            //Add element string
            hpile.AddElement(element2);
            ////Add element character
            hpile.AddElement(element3);
            ////Add element double
            hpile.AddElement(element4);
        }
    }
}
